package com.example.voucher.config;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Objects;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.yaml.snakeyaml.Yaml;

import com.example.voucher.config.bo.ReducingConfigBO;
import com.example.voucher.config.third.ThirdAccountBean;

@Component
public class VoucherConfigLoader implements CommandLineRunner {

    private static final Logger LOGGER = LoggerFactory.getLogger(VoucherConfigLoader.class);
    private static final Pattern GROUPING_REDUCING_PATTERN = Pattern.compile("^groupingReducing.yml$");
    private static final Pattern THIRD_ACCOUNT_PATTERN = Pattern.compile("^thirdAccount(_(.+))?.yml$");
    private static final Pattern MAPPING_PATTERN =
        Pattern.compile("^mapping_([\\w^_]*)_([\\w^_]*)_([\\w\\.]*)\\.properties$");

    public String DEFAULT_VOUCHER_ITEM_CONFIG_DIR = "/config/voucher";

    @Autowired
    private SubjectConfigRegister subjectConfig;
    @Autowired
    private ThirdAccountRegister thirdAccountRegister;

    @Override
    public void run(String... args) throws Exception {
        URL url = VoucherConfigLoader.class.getResource(DEFAULT_VOUCHER_ITEM_CONFIG_DIR);
        Assert.notNull(url, "科目相关配置的存放路径有误");
        File dir = new File(url.getFile());
        Assert.isTrue(dir.exists() && dir.isDirectory(), "科目相关配置的存放路径有误");

        Files.walkFileTree(dir.toPath(), new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException {
                Objects.requireNonNull(path);
                Objects.requireNonNull(attrs);
                if (attrs.isRegularFile()) {
                    String fileName = path.getFileName().toString();
                    if (GROUPING_REDUCING_PATTERN.matcher(fileName).matches()) {
                        // 读取分组汇总相关配置，注册
                        Yaml yaml = new Yaml();
                        ReducingConfigBO reducingConfig =
                            yaml.loadAs(Files.newInputStream(path), ReducingConfigBO.class);
                        subjectConfig.registerReducingConfig(reducingConfig);
                    } else {
                        Matcher matcher = MAPPING_PATTERN.matcher(fileName);
                        if (matcher.matches()) {
                            // 读取映射相关配置，注册
                            String tenantCode = matcher.group(1);
                            String scenarioCode = matcher.group(2);
                            String subject = matcher.group(3);
                            Properties prop = new Properties();
                            prop.load(Files.newBufferedReader(path, Charset.forName("UTF-8")));
                            subjectConfig.registerMappingConfig(tenantCode, scenarioCode, subject, prop);
                        } else {
                            matcher = THIRD_ACCOUNT_PATTERN.matcher(fileName);
                            if (matcher.matches()) {
                                String env = matcher.group(2);
                                Yaml yaml = new Yaml();
                                ThirdAccountBean thirdAccount = yaml.loadAs(Files.newInputStream(path), ThirdAccountBean.class);
                                thirdAccountRegister.registerLocalAccountConfig(env, thirdAccount);
                            }
                        }
                    }
                }
                return FileVisitResult.CONTINUE;
            }
        });
    }

}
